package xredis

import (
	"context"
	"github.com/redis/go-redis/v9"
	"strings"
	"time"
)

type RedisConfig struct {
	Addr         string `json:"addr"`
	Password     string `json:"password"`
	DB           int    `json:"DB"`
	DialTimeout  int64  `json:"dialTimeout"`
	ReadTimeout  int64  `json:"readTimeout"`
	WriteTimeout int64  `json:"writeTimeout"`
	IdleTimeout  int64  `json:"idleTimeout"` // 连接生效时间，默认5分钟
	MaxRetries   int    `json:"maxRetries"`
	PoolSize     int    `json:"poolSize"`
	MinIdleConn  int    `json:"minIdleConn"`
	KeyPrefix    string `json:"keyPrefix"`
}

// Client 支持key前缀的Redis单点客户端
// 关于key前缀，X开头的方法不支持
//   - 示例：
//   - client,_ := xredis.NewClient(cfg)
//   - client.Set(ctx, key, '1', 0) // 支持key前缀
//   - client.XAdd() // 不支持key前缀
//   - client.Do(ctx, "set", "key", "value") // 不支持key前缀
//   - client.Client.Set() // 不支持key前缀
type Client struct {
	*redis.Client
	keyPrefix struct {
		Prefix string
		enable bool
	}
}

func NewClient(config *RedisConfig) (client *Client, err error) {
	options := &redis.Options{
		Addr:         config.Addr,
		Password:     config.Password,
		DB:           config.DB,
		DialTimeout:  time.Duration(config.DialTimeout) * time.Millisecond,
		ReadTimeout:  time.Duration(config.ReadTimeout) * time.Millisecond,
		WriteTimeout: time.Duration(config.WriteTimeout) * time.Millisecond,
		MaxRetries:   config.MaxRetries,
		PoolSize:     config.PoolSize,
		MinIdleConns: config.MinIdleConn,
	}

	rdb := redis.NewClient(options)
	client = &Client{
		Client: rdb,
		keyPrefix: struct {
			Prefix string
			enable bool
		}{Prefix: config.KeyPrefix, enable: true},
	}
	return
}

func (c *Client) KeyPrefix() string {
	if c.IsEnableKeyPrefix() {
		return c.keyPrefix.Prefix
	}
	return ""
}

func (c *Client) EnableKeyPrefix() {
	c.keyPrefix.enable = true
}

func (c *Client) DisableKeyPrefix() {
	c.keyPrefix.enable = false
}

func (c *Client) IsEnableKeyPrefix() bool {
	return c.keyPrefix.enable && c.keyPrefix.Prefix != ""
}

func (c *Client) formatKeys(keys ...string) []string {
	if !c.IsEnableKeyPrefix() {
		return keys
	}

	ks := make([]string, 0)
	for _, v := range keys {
		if strings.HasPrefix(v, c.KeyPrefix()) {
			ks = append(ks, v)
		} else {
			ks = append(ks, c.KeyPrefix()+v)
		}
	}

	return ks
}

type Logging interface {
	Printf(ctx context.Context, format string, v ...interface{})
}

func SetLogger(logger Logging) {
	redis.SetLogger(logger)
}
